package com.seafood.service.impl;

import com.seafood.common.PageResult;
import com.seafood.dto.*;
import com.seafood.entity.User;
import com.seafood.exception.BusinessException;
import com.seafood.repository.UserRepository;
import com.seafood.service.AdminUserService;
import com.seafood.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 管理员用户管理服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional
public class AdminUserServiceImpl implements AdminUserService {
    
    private final UserRepository userRepository;
    private final UserService userService;
    private final PasswordEncoder passwordEncoder;
    
    private static final String DEFAULT_PASSWORD = "123456";
    
    @Override
    @Transactional(readOnly = true)
    public PageResult<UserDTO> getUserList(UserQueryDTO queryDTO) {
        // 构建查询条件
        Specification<User> spec = buildUserSpecification(queryDTO);
        
        // 构建分页和排序
        Sort sort = buildSort(queryDTO.getSortBy(), queryDTO.getSortDirection());
        Pageable pageable = PageRequest.of(queryDTO.getPage() - 1, queryDTO.getSize(), sort);
        
        // 执行查询
        Page<User> userPage = userRepository.findAll(spec, pageable);
        
        // 转换为DTO
        List<UserDTO> userDTOs = userPage.getContent().stream()
                .map(userService::convertToDTO)
                .collect(Collectors.toList());
        
        return PageResult.of(userDTOs, userPage.getTotalElements(), userPage.getTotalPages(),
                queryDTO.getPage() - 1, queryDTO.getSize(), userPage.isFirst(), userPage.isLast());
    }
    
    @Override
    @Transactional(readOnly = true)
    public UserDTO getUserDetail(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new BusinessException("用户不存在"));
        return userService.convertToDTO(user);
    }
    @Override
    public Long getUserIdByName(String username){
       User user= userRepository.findByUsername(username).orElseThrow(()->new BusinessException("用户名不存在"));
       return user.getId();
    }
    
    @Override
    public UserDTO createUser(UserCreateDTO createDTO) {
        // 验证用户名是否已存在
        if (userRepository.existsByUsername(createDTO.getUsername())) {
            throw new BusinessException("用户名已存在");
        }
        
        // 验证邮箱是否已存在
        if (userRepository.existsByEmail(createDTO.getEmail())) {
            throw new BusinessException("邮箱已存在");
        }
        
        // 验证手机号是否已存在
        if (StringUtils.hasText(createDTO.getPhone()) && userRepository.existsByPhone(createDTO.getPhone())) {
            throw new BusinessException("手机号已存在");
        }
        
        // 验证密码和确认密码
        if (!StringUtils.hasText(createDTO.getPassword())) {
            throw new BusinessException("密码不能为空");
        }
        
        if (!createDTO.getPassword().equals(createDTO.getConfirmPassword())) {
            throw new BusinessException("两次输入的密码不一致");
        }
        
        // 创建用户实体
        User user = new User();
        user.setUsername(createDTO.getUsername());
        user.setPassword(passwordEncoder.encode(createDTO.getPassword()));
        user.setEmail(createDTO.getEmail());
        user.setPhone(createDTO.getPhone());
        user.setRealName(createDTO.getRealName());
        
        try {
            user.setUserType(User.UserType.valueOf(createDTO.getUserType()));
            user.setStatus(User.UserStatus.valueOf(createDTO.getStatus()));
        } catch (IllegalArgumentException e) {
            throw new BusinessException("无效的用户类型或状态");
        }
        
        user.setCompanyName(createDTO.getCompanyName());
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());
        
        // 保存用户
        User savedUser = userRepository.save(user);
        
        log.info("管理员创建用户: userId={}, username={}, userType={}", 
                savedUser.getId(), savedUser.getUsername(), savedUser.getUserType());
        
        return userService.convertToDTO(savedUser);
    }
    
    @Override
    public UserDTO updateUser(Long id, UserUpdateDTO updateDTO) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new BusinessException("用户不存在"));
        
        // 不能修改管理员的信息
        if (user.getUserType() == User.UserType.ADMIN) {
            throw new BusinessException("不能修改管理员信息");
        }
        
        // 验证邮箱是否已存在（排除当前用户）
        if (!user.getEmail().equals(updateDTO.getEmail()) && 
            userRepository.existsByEmail(updateDTO.getEmail())) {
            throw new BusinessException("邮箱已存在");
        }
        
        // 验证手机号是否已存在（排除当前用户）
        if (StringUtils.hasText(updateDTO.getPhone()) && 
            !Objects.equals(user.getPhone(), updateDTO.getPhone()) &&
            userRepository.existsByPhone(updateDTO.getPhone())) {
            throw new BusinessException("手机号已存在");
        }
        
        // 更新用户信息
        user.setEmail(updateDTO.getEmail());
        user.setPhone(updateDTO.getPhone());
        user.setRealName(updateDTO.getRealName());
        
        try {
            user.setUserType(User.UserType.valueOf(updateDTO.getUserType()));
            user.setStatus(User.UserStatus.valueOf(updateDTO.getStatus()));
        } catch (IllegalArgumentException e) {
            throw new BusinessException("无效的用户类型或状态");
        }
        
        user.setCompanyName(updateDTO.getCompanyName());
        user.setUpdatedAt(LocalDateTime.now());
        
        // 保存更新
        User savedUser = userRepository.save(user);
        
        log.info("管理员更新用户信息: userId={}, username={}", 
                savedUser.getId(), savedUser.getUsername());
        
        return userService.convertToDTO(savedUser);
    }
    
    @Override
    public void updateUserStatus(Long id, UserStatusUpdateDTO statusUpdateDTO) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new BusinessException("用户不存在"));
        
        // 不能修改自己的状态
        if (user.getUserType() == User.UserType.ADMIN) {
            throw new BusinessException("不能修改管理员状态");
        }
        
        try {
            User.UserStatus newStatus = User.UserStatus.valueOf(statusUpdateDTO.getStatus());
            user.setStatus(newStatus);
            userRepository.save(user);
            
            log.info("管理员更新用户状态: userId={}, newStatus={}, reason={}", 
                    id, newStatus, statusUpdateDTO.getReason());
            
            // TODO: 发送状态变更通知
            if (statusUpdateDTO.getSendNotification()) {
                sendStatusChangeNotification(user, newStatus, statusUpdateDTO.getReason());
            }
            
        } catch (IllegalArgumentException e) {
            throw new BusinessException("无效的用户状态: " + statusUpdateDTO.getStatus());
        }
    }
    
    @Override
    public String resetUserPassword(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new BusinessException("用户不存在"));
        
        // 不能重置管理员密码
        if (user.getUserType() == User.UserType.ADMIN) {
            throw new BusinessException("不能重置管理员密码");
        }
        
        String newPassword = generateRandomPassword();
        user.setPassword(passwordEncoder.encode(newPassword));
        userRepository.save(user);
        
        log.info("管理员重置用户密码: userId={}, username={}", id, user.getUsername());
        
        // TODO: 发送密码重置通知
        sendPasswordResetNotification(user, newPassword);
        
        return newPassword;
    }
    
    @Override
    public void deleteUser(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new BusinessException("用户不存在"));
        
        // 不能删除管理员
        if (user.getUserType() == User.UserType.ADMIN) {
            throw new BusinessException("不能删除管理员账户");
        }
        
        // 软删除：设置状态为INACTIVE
        user.setStatus(User.UserStatus.INACTIVE);
        userRepository.save(user);
        
        log.info("管理员删除用户: userId={}, username={}", id, user.getUsername());
    }
    
    @Override
    @Transactional(readOnly = true)
    public Map<String, Object> getUserStatistics() {
        Map<String, Object> statistics = new HashMap<>();
        
        // 总用户数
        long totalUsers = userRepository.count();
        statistics.put("totalUsers", totalUsers);
        
        // 活跃用户数
        long activeUsers = userRepository.countByStatus(User.UserStatus.ACTIVE);
        statistics.put("activeUsers", activeUsers);
        
        // 非活跃用户数
        long inactiveUsers = userRepository.countByStatus(User.UserStatus.INACTIVE);
        statistics.put("inactiveUsers", inactiveUsers);
        
        // 按类型统计
        Map<String, Long> userTypeStats = new HashMap<>();
        for (User.UserType type : User.UserType.values()) {
            long count = userRepository.countByUserType(type);
            userTypeStats.put(type.name(), count);
        }
        statistics.put("userTypeStats", userTypeStats);
        
        // 今日新增用户
        LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
        long todayNewUsers = userRepository.countByCreatedAtGreaterThanEqual(todayStart);
        statistics.put("todayNewUsers", todayNewUsers);
        
        // 本月新增用户
        LocalDateTime monthStart = LocalDateTime.now().withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0);
        long monthNewUsers = userRepository.countByCreatedAtGreaterThanEqual(monthStart);
        statistics.put("monthNewUsers", monthNewUsers);
        
        // 最近7天注册趋势
        List<Map<String, Object>> registrationTrend = getRegistrationTrend(7);
        statistics.put("registrationTrend", registrationTrend);
        
        return statistics;
    }
    
    @Override
    public void batchUpdateUserStatus(UserStatusUpdateDTO statusUpdateDTO) {
        if (statusUpdateDTO.getUserIds() == null || statusUpdateDTO.getUserIds().isEmpty()) {
            throw new BusinessException("用户ID列表不能为空");
        }
        
        List<User> users = userRepository.findAllById(statusUpdateDTO.getUserIds());
        
        if (users.size() != statusUpdateDTO.getUserIds().size()) {
            throw new BusinessException("部分用户不存在");
        }
        
        // 检查是否包含管理员
        boolean hasAdmin = users.stream()
                .anyMatch(user -> user.getUserType() == User.UserType.ADMIN);
        if (hasAdmin) {
            throw new BusinessException("不能批量修改管理员状态");
        }
        
        try {
            User.UserStatus newStatus = User.UserStatus.valueOf(statusUpdateDTO.getStatus());
            
            users.forEach(user -> user.setStatus(newStatus));
            userRepository.saveAll(users);
            
            log.info("管理员批量更新用户状态: userIds={}, newStatus={}, reason={}", 
                    statusUpdateDTO.getUserIds(), newStatus, statusUpdateDTO.getReason());
            
            // TODO: 批量发送通知
            if (statusUpdateDTO.getSendNotification()) {
                users.forEach(user -> 
                    sendStatusChangeNotification(user, newStatus, statusUpdateDTO.getReason()));
            }
            
        } catch (IllegalArgumentException e) {
            throw new BusinessException("无效的用户状态: " + statusUpdateDTO.getStatus());
        }
    }
    
    /**
     * 构建用户查询条件
     */
    private Specification<User> buildUserSpecification(UserQueryDTO queryDTO) {
        return (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            // 用户类型过滤
            if (StringUtils.hasText(queryDTO.getUserType())) {
                try {
                    User.UserType userType = User.UserType.valueOf(queryDTO.getUserType());
                    predicates.add(criteriaBuilder.equal(root.get("userType"), userType));
                } catch (IllegalArgumentException e) {
                    // 忽略无效的用户类型
                }
            }
            
            // 状态过滤
            if (StringUtils.hasText(queryDTO.getStatus())) {
                try {
                    User.UserStatus status = User.UserStatus.valueOf(queryDTO.getStatus());
                    predicates.add(criteriaBuilder.equal(root.get("status"), status));
                } catch (IllegalArgumentException e) {
                    // 忽略无效的状态
                }
            }
            
            // 关键词搜索
            if (StringUtils.hasText(queryDTO.getKeyword())) {
                String keyword = "%" + queryDTO.getKeyword().toLowerCase() + "%";
                Predicate usernamePredicate = criteriaBuilder.like(
                    criteriaBuilder.lower(root.get("username")), keyword);
                Predicate emailPredicate = criteriaBuilder.like(
                    criteriaBuilder.lower(root.get("email")), keyword);
                Predicate phonePredicate = criteriaBuilder.like(
                    criteriaBuilder.lower(root.get("phone")), keyword);
                Predicate realNamePredicate = criteriaBuilder.like(
                    criteriaBuilder.lower(root.get("realName")), keyword);
                
                predicates.add(criteriaBuilder.or(
                    usernamePredicate, emailPredicate, phonePredicate, realNamePredicate));
            }
            
            // 时间范围过滤
            if (StringUtils.hasText(queryDTO.getStartDate())) {
                try {
                    LocalDateTime startDate = LocalDateTime.parse(queryDTO.getStartDate() + "T00:00:00");
                    predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createdAt"), startDate));
                } catch (Exception e) {
                    // 忽略无效的日期格式
                }
            }
            
            if (StringUtils.hasText(queryDTO.getEndDate())) {
                try {
                    LocalDateTime endDate = LocalDateTime.parse(queryDTO.getEndDate() + "T23:59:59");
                    predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("createdAt"), endDate));
                } catch (Exception e) {
                    // 忽略无效的日期格式
                }
            }
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
    }
    
    /**
     * 构建排序
     */
    private Sort buildSort(String sortBy, String sortDirection) {
        // 默认排序字段
        if (!StringUtils.hasText(sortBy)) {
            sortBy = "createdAt";
        }
        
        // 验证排序字段
        Set<String> allowedSortFields = Set.of("id", "username", "email", "userType", "status", "createdAt", "updatedAt");
        if (!allowedSortFields.contains(sortBy)) {
            sortBy = "createdAt";
        }
        
        // 排序方向
        Sort.Direction direction = "ASC".equalsIgnoreCase(sortDirection) ? 
            Sort.Direction.ASC : Sort.Direction.DESC;
        
        return Sort.by(direction, sortBy);
    }
    
    /**
     * 获取注册趋势数据
     */
    private List<Map<String, Object>> getRegistrationTrend(int days) {
        List<Map<String, Object>> trend = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        
        for (int i = days - 1; i >= 0; i--) {
            LocalDateTime date = LocalDateTime.now().minusDays(i);
            LocalDateTime dayStart = date.withHour(0).withMinute(0).withSecond(0);
            LocalDateTime dayEnd = date.withHour(23).withMinute(59).withSecond(59);
            
            long count = userRepository.countByCreatedAtBetween(dayStart, dayEnd);
            
            Map<String, Object> dayData = new HashMap<>();
            dayData.put("date", date.format(formatter));
            dayData.put("count", count);
            trend.add(dayData);
        }
        
        return trend;
    }
    
    /**
     * 生成随机密码
     */
    private String generateRandomPassword() {
        // 简单实现，生成8位随机数字密码
        Random random = new Random();
        StringBuilder password = new StringBuilder();
        for (int i = 0; i < 8; i++) {
            password.append(random.nextInt(10));
        }
        return password.toString();
    }
    
    /**
     * 发送状态变更通知
     */
    private void sendStatusChangeNotification(User user, User.UserStatus newStatus, String reason) {
        // TODO: 实现邮件/短信通知
        log.info("发送用户状态变更通知: userId={}, status={}, reason={}", 
                user.getId(), newStatus, reason);
    }
    
    /**
     * 发送密码重置通知
     */
    private void sendPasswordResetNotification(User user, String newPassword) {
        // TODO: 实现邮件/短信通知
        log.info("发送密码重置通知: userId={}", user.getId());
    }
}